#ifndef __H_DB_M__
#define __H_DB_M__

#include "util.hpp"
#include <mutex>
#include <cassert>


class user_table
{
public:
    user_table(const string& host, const string& username, const string& password,
                        const string& dbname, uint16_t port = 3306)
    {
        _mysql = mysql_util::mysql_create(host, username , password, dbname, port);
        assert(_mysql != NULL);

    }
    ~user_table()
    {
        mysql_util::mysql_destroy(_mysql);
        _mysql = NULL;
    }
    // 新增用户
    bool insert(Json::Value& user)
    {
        // 1.校验用户名密码
        if(user["username"].isNull() || user["password"].isNull())
        {
            ELOG("用户名/密码为空");
            return false;
        }
        // 2.执行语句
    #define INSERT_EXEC "insert user values(null, '%s', password('%s'), 1000, 0, 0);"
        char sql[4096] = {0};
        sprintf(sql, INSERT_EXEC, user["username"].asCString(),user["password"].asCString());
        if(mysql_util::mysql_execute(_mysql, sql) == false)
        { 
            ELOG("执行语句失败！");
            return false;
        }
        return true;
    }
    // 用户登录
    bool login(Json::Value& user)
    {
        // 1.校验用户名密码
        if(user["username"].isNull() || user["password"].isNull())
        {
            ELOG("用户名/密码为空");
            return false;
        }
        // 2. 用用户名和密码共同作为条件进行查找
    #define LOG_EXEC "select id, score, total_count, win_count from user where username='%s' and password=password('%s');"
        char sql[4096] = {0};
        sprintf(sql, LOG_EXEC, user["username"].asCString(),user["password"].asCString());

        MYSQL_RES* res = NULL;
        {
            unique_lock<mutex> lock(_mutex);
            if(mysql_util::mysql_execute(_mysql, sql) == false)
            {
                ELOG("用户名/密码错误！");
                return false;
            }
            // 3. 找到了就把结果保存到本地
            res = mysql_store_result(_mysql);
            if(res == NULL)
            {
                ELOG("保存结果集失败！");
                return false;
            }
        }
        
        int row_num = mysql_num_rows(res);
        if(row_num != 1)
        {
            DLOG("结果集中没有数据！");
            return false;
        }
        // 4. 将用户信息保存到json格式里
        MYSQL_ROW row = mysql_fetch_row(res);
        user["id"] = (Json::UInt64)stol(row[0]);
        user["score"] = (Json::UInt64)stol(row[1]);
        user["total_count"] = stoi(row[2]);
        user["win_count"] = stoi(row[3]);

        // 5. 释放结果集
        mysql_free_result(res);
        return true;
    }
    // 
    bool select_by_name(const string& name, Json::Value& user)
    {
    #define SELECT_NAME "select id, score, total_count, win_count from user where username='%s';"
        // 1. 数据库中查找该用户是否存在
        char sql[4096] = {0};
        sprintf(sql, SELECT_NAME, name.c_str());

        MYSQL_RES* res = NULL;
        {
            unique_lock<mutex> lock(_mutex);
            if(mysql_util::mysql_execute(_mysql, sql) == false)
            {
                DLOG("该用户不存在: %s" , name.c_str());
                return false;
            }
            // 2. 存在要保存结果集
            res = mysql_store_result(_mysql);
            if(res == NULL)
            {
                ELOG("保存结果集失败！");
                return false;
            }
        }
        int row_num = mysql_num_rows(res);
        if(row_num != 1)
        {
            DLOG("结果集中没有数据！");
            return false;            
        }
        MYSQL_ROW row = mysql_fetch_row(res);
        user["id"] = (Json::UInt64)stol(row[0]);
        user["username"] = name;
        user["score"] = (Json::UInt64)stol(row[1]);
        user["total_count"] = stoi(row[2]);
        user["win_count"] = stoi(row[3]);

        // 3. 释放结果集
        mysql_free_result(res);
        return true;
    }
    bool select_by_id(uint64_t id, Json::Value& user)
    {
    #define SELECT_ID "select username, score, total_count, win_count from user where id=%d;"
        // 1. 数据库中查找该用户是否存在
        char sql [4096] = {0};
        sprintf(sql, SELECT_ID, id);

        MYSQL_RES* res = NULL;
        {
            unique_lock<mutex> lock(_mutex);
            if(mysql_util::mysql_execute(_mysql, sql) == false)
            {
                DLOG("该 %d 不存在", id);
                return false;
            }
            // 2. 查找到要保存结果集
            res = mysql_store_result(_mysql);
            if(res == NULL)
            {
                DLOG("保存结果失败！");
                return false;
            }
        }
        int row_num = mysql_num_rows(res);
        if(row_num != 1)
        {
            DLOG("结果集中没有数据！");
            return false;
        }
        MYSQL_ROW row = mysql_fetch_row(res);
        user["id"] = (Json::UInt64)id;
        user["username"] = row[0];
        user["score"] = (Json::UInt64)stol(row[1]);
        user["total_count"] = stoi(row[2]);
        user["win_count"] = stoi(row[3]);

        // 3. 释放结果集
        mysql_free_result(res);
        return true;
    }
    // 胜利
    bool win(uint64_t uid)
    {
    #define WIN_USER "update user set score=score+30, total_count=total_count+1, win_count=win_count+1 where id=%d;"
        // 胜利时需要给玩家增加天梯积分，对战总场次、胜利场次
        char sql[4096] = {0};
        sprintf(sql, WIN_USER, uid);
        if(mysql_util::mysql_execute(_mysql, sql) == false)
        {
            ELOG("修改胜利玩家信息失败！");
            return false;
        }
        return true;
    }
    // 失败
    bool lose(uint64_t uid)
    {
    #define LOSE_USER "update user set score=score-30, total_count=total_count+1 where id=%d;"
        // 失败时需要将玩家的天梯积分减少，对战总场次增加
        char sql[4096] = {0};
        sprintf(sql, LOSE_USER, uid);
        if(mysql_util::mysql_execute(_mysql, sql) == false)
        {
            ELOG("修改失败玩家信息失败！");
            return false;
        }
        return true;
    }
    
private:
    MYSQL* _mysql;
    mutex _mutex;
};

#endif